#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <cstring>

// 使用特殊字符作为分隔符来解决粘包问题,处理独立报文
#define SEP "X"
#define SEP_LEN strlen(SEP)
// 用于序列化和反序列化
#define SPACE " "
#define SPACE_LEN strlen(SPACE)

// buffer: 输入输出型参数
// out: 输出型参数
// buffer中可能会存在多个报文,没有报文是以SEP作为分隔符的
// 我们想要将不同的报文切分好,放入到out中
void SpliteMessage(std::string& buffer, std::vector<std::string>& out)
{
    while(true)
    {
        auto pos = buffer.find(SEP);
        if(pos == std::string::npos) break;
        std::string message = buffer.substr(0, pos);
        buffer.erase(0, pos + SEP_LEN);
        out.emplace_back(message);
    }    
}

// 给报文加上分隔符
std::string Encode(std::string& s)
{
    return s + SEP;
}

// 去除报文中的分割符
std::string Decode(std::string& s)
{
    auto pos = s.find(SEP);
    // s中没有一个完整的报文时,返回空串
    // s中有一个完整的报文时,返回该报文
    if(pos == std::string::npos) return "";
    std::string ret = s.substr(0, pos);
    s.erase(0, pos + SEP_LEN);
    return ret;
}

// 网络版计算器的 Request 和 Response
class Request
{
public:
    // 序列化
    std::string Serialize()
    {
        std::string str;
        str = std::to_string(_x);
        str += SPACE;
        str += _op;
        str += SPACE;
        str += std::to_string(_y);
        return str;
    }

    // 反序列化
    bool Deserialized(const std::string &str) 
    {
        std::size_t left = str.find(SPACE);
        if (left == std::string::npos)
            return false;
        std::size_t right = str.rfind(SPACE);
        if (right == std::string::npos)
            return false;
        _x = atoi(str.substr(0, left).c_str());
        _y = atoi(str.substr(right + SPACE_LEN).c_str());
        if (left + SPACE_LEN > str.size())
            return false;
        else
            _op = str[left + SPACE_LEN];
        return true;
    }

public:
    Request()
    {}

    Request(int x, int y, char op) 
        : _x(x)
        , _y(y)
        , _op(op)
    {}

    ~Request() {}

public:
    int _x;   
    int _y;   
    char _op; 
};

class Response
{
public:
    // 序列化
    std::string Serialize()
    {

        std::string s;
        s = std::to_string(_code);
        s += SPACE;
        s += std::to_string(_ret);

        return s;
    }

    // 反序列化
    bool Deserialized(const std::string &s)
    {
        std::size_t pos = s.find(SPACE);
        if (pos == std::string::npos)
            return false;
        _code = atoi(s.substr(0, pos).c_str());
        _ret = atoi(s.substr(pos + SPACE_LEN).c_str());
        return true;
    }

public:
    Response()
    {}

    Response(int ret, int code) 
        : _ret(ret)
        , _code(code)
    {}

    ~Response() {}

public:
    int _ret; // 计算结果
    int _code;   // 计算结果的状态码
};